﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Xml;
using Microsoft.Extensions.Configuration.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Net.NetworkInformation;

namespace TankQiandaoWx
{
    class Program
    {
        //Nuget中添加引用Microsoft.Extensions.Configuration
        //Nuget中添加引用Microsoft.Extensions.Configuration.Xml
        static void Main(string[] args)
        {
            Log.AddLog("开始执行...");
            try
            {
                //检查网络是否连接
                Ping ping = new Ping();
                string address = "www.baidu.com";
                //超时时间毫秒
                PingReply pingReply = ping.Send(address, 10000);
                string status = pingReply.Status.ToString().ToLower();
                if (!status.Equals("success"))
                {
                    Log.AddLog("网络未连接");
                    return;
                }
            }
            //System.Net.NetworkInformation.PingException
            //System.Net.Sockets.SocketException
            catch (System.Net.NetworkInformation.PingException ex)
            {
                var exInner = ex.InnerException as System.Net.Sockets.SocketException;
                if (exInner != null && exInner.ErrorCode == 11001)
                {
                    Log.AddLog("网络未连接");
                    return;
                }
            }

            IConfigurationBuilder builder = null;
            IConfiguration _configuration = null;
            IConfigurationBuilder jsonBuilder = null;
            IConfiguration _jsonConfig = null;
            try
            {
                builder = new ConfigurationBuilder().SetBasePath(AppDomain.CurrentDomain.BaseDirectory).AddXmlFile("config.xml");
                _configuration = builder.Build();

                jsonBuilder = new ConfigurationBuilder().SetBasePath(AppDomain.CurrentDomain.BaseDirectory).AddJsonFile("SignRecored.json");
                _jsonConfig = jsonBuilder.Build();
            }
            catch (Exception ex)
            {
                Log.AddLog("加载配置文件异常：" + ex.ToString());
            }
            //string token = _configuration["token"];
            //string cookie = _configuration["cookie"];
            //string loginUrl = _configuration["loginUrl"];
            //string userInfo = _configuration["userInfo"];

            string _signTimes = string.Empty;
            string _lastDate = string.Empty;
            string _state = string.Empty;
            string _failCount = string.Empty;
            try
            {
                _signTimes = _jsonConfig["SignTimes"];
                _lastDate = _jsonConfig["LastDate"];
                _state = _jsonConfig["State"];
                _failCount = _jsonConfig["FailCount"];
            }
            catch (Exception)
            {
                Log.AddLog("配置文件格式不正确，请用格式：{ \"SignTimes\": 2, \"LastDate\":\"2018-10-07\" }");
                return;
            }
            //读取已经签到的次数        
            int signTimes = Convert.ToInt32(_signTimes);
            //上次签到日期
            DateTime lastDate = Convert.ToDateTime(_lastDate);
            //是否签到成功，1=成功，0=失败
            int state = Convert.ToInt32(_state);


            //检查是否是当天重复签到
            if (DateTime.Now.Date == lastDate.Date)
            {
                if (state == 1)
                {
                    //如果当天已经签到成功，则不进行以下签到了
                    Log.AddLog("当天已经签到成功，勿需再执行签到");
                    return;
                }
            }

            //重置签到次数记录
            if (DateTime.Now.Day == 1)
            {
                signTimes = 0;
                RecoredSignTimesJsonFile(0, 0);
            }
            else if ((DateTime.Now - lastDate).TotalDays > 0 && DateTime.Now.Month != lastDate.Month && signTimes >= 21)
            {
                signTimes = 0;
                RecoredSignTimesJsonFile(0, 0);
            }

            //读取每月限制次数
            string _MonthLimitCount = _configuration["MonthLimitCount"];
            int monthLimitCount = Convert.ToInt32(_MonthLimitCount);

            if (signTimes == monthLimitCount && DateTime.Now.Day != 1)
            {
                Log.AddLog("以满签到" + monthLimitCount + "次限制，不执行签到");
                return;
            }    

            //签到地址
            string gameInsideUrl = _configuration["gameInside"];
            string json = GamesInsideQiandao(gameInsideUrl);
            //尝试次数用完，签到失败发送邮件
            if (isError)
            {
                //失败几次发送通知邮件，读取配置文件
                string _failCountSendEmail = _configuration["FailCountSendEmail"];
                int failCountSendEmail = Convert.ToInt32(_failCountSendEmail);
                //当天已经签到失败次数
                int failCount = Convert.ToInt32(_failCount);

                failCount++;
                if (failCount >= failCountSendEmail)
                {
                    Log.AddLog($"已满失败{failCountSendEmail}次条件，发送签到失败通知邮件");
                    EmailSend.SendEmail(json);
                }
                RecoredSignTimesJsonFile(signTimes, 0, failCount);
            }
            else
            {
                //累计签到次数记录写入文件
                signTimes++;
                RecoredSignTimesJsonFile(signTimes, 1);
                Log.AddLog("游戏内部签到成功");
            }
            Log.AddLog("退出程序");


#if DEBUG
            Console.ReadKey();
#endif
        }

        /// <summary>
        /// 将签到次数记录到文件
        /// </summary>
        /// <param name="signTimes">签到成功次数</param>
        /// <param name="state">是否签到成功，1=成功，0=失败</param>
        /// <param name="failCount">失败次数累计（当天）</param>
        internal static void RecoredSignTimesJsonFile(int signTimes, int state, int failCount = 0)
        {
            string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SignRecored.json");
            FileStream fileStream = new FileStream(filePath, FileMode.Create);
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.AppendLine("{");
            //成功签到次数累计
            stringBuilder.AppendLine("\"SignTimes\": " + signTimes + ",");
            //签到状态
            stringBuilder.AppendLine("\"State\": " + state + ",");
            //失败次数累计（当天）
            stringBuilder.AppendLine("\"FailCount\": " + failCount + ",");
            stringBuilder.AppendLine("\"LastDate\": \"" + DateTime.Now.ToString("yyyy-MM-dd") + "\"");
            stringBuilder.AppendLine("}");
            string txt = stringBuilder.ToString();
            byte[] stringBytes = System.Text.Encoding.UTF8.GetBytes(txt);
            fileStream.Write(stringBytes, 0, stringBytes.Length);
            fileStream.Flush();
            fileStream.Close();
            fileStream.Dispose();
        }

        public static string Login(string loginUrl, string data = null)
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(loginUrl);
            try
            {
                request.Method = "POST";
                //request.KeepAlive = true;
                request.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
                Stream stream = request.GetRequestStream();
                if (!string.IsNullOrWhiteSpace(data))
                {
                    byte[] bytes = Encoding.UTF8.GetBytes(data);
                    stream.Write(bytes, 0, bytes.Length);
                }
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                Stream responseStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(responseStream);
                string backMsg = reader.ReadToEnd();
                Console.WriteLine(backMsg);
                Log.AddLog(backMsg + System.Environment.NewLine);

                CookieCollection colletion = response.Cookies;
                StringBuilder sb = new StringBuilder();
                foreach (var item in colletion)
                {
                    sb.Append(item.ToString() + ";");
                }
                string cookieStr = sb.ToString().TrimEnd(';');
                return cookieStr;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Log.AddLog(ex.ToString() + System.Environment.NewLine);
            }
            return "";
        }

        /// <summary>
        /// 签到
        /// </summary>
        public static void Qiandao(string token, string cookieStr)
        {
            string url = "https://hero.kongzhong.com/home/SignWot/sign";
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            try
            {
                CookieContainer cookieContainer = new CookieContainer();
                cookieStr = cookieStr.Replace(" ", "");
                string[] arr = cookieStr.Split(';');
                foreach (var item in arr)
                {
                    string name = item.Split('=')[0];
                    string val = item.Split('=')[1];
                    Cookie cookie = new Cookie();
                    cookie.Name = name;
                    cookie.Value = val;
                    cookie.Path = "/";
                    cookie.Domain = request.RequestUri.Host;
                    cookieContainer.Add(cookie);
                }
                request.Referer = "https://hero.kongzhong.com/home/signwot/index/uid/430815.html";
                request.Method = "POST";
                //request.KeepAlive = true;
                request.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
                //request.Headers.Add("Origin", "https://hero.kongzhong.com");
                request.CookieContainer = cookieContainer;
                //string data = "token=xsubpm1404353542&oneid=430815&lid=21&rid=21";
                string data = token;
                Stream stream = request.GetRequestStream();
                byte[] bytes = Encoding.UTF8.GetBytes(data);
                stream.Write(bytes, 0, bytes.Length);
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                Stream responseStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(responseStream);
                string backMsg = reader.ReadToEnd();
                Console.WriteLine(backMsg);
                Log.AddLog(backMsg + System.Environment.NewLine);
            }
            catch (Exception ex)
            {
                Log.AddLog(ex.ToString() + System.Environment.NewLine);
                Console.WriteLine(ex.ToString());
            }
        }

        /// <summary>
        /// 签到尝试次数
        /// </summary>
        static int count = 0;
        /// <summary>
        /// 是否签到失败
        /// </summary>
        static bool isError = false;
        /// <summary>
        /// 游戏内部签到
        /// </summary>
        public static string GamesInsideQiandao(string url)
        {
            string msg = WebClientGet(url);
            string json = msg.Replace("jQuery170519896756211045_1527929958706(", "");
            json = json.Replace(")", "");

            //不重试签到了
            //count++;
            dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json);
            if (jsonObj != null && jsonObj.state.Value != "1")
            {
                isError = true;
                Log.AddLog($"签到失败{json}");

                ////20秒后重试
                //Thread.Sleep(600 * 1000);
                //if (count <= 4)
                //{
                //    GamesInsideQiandao(url);
                //}
                //else
                //{
                //    isError = true;
                //}
            }

            return json;
        }

        /// <summary>
        /// 同步方式，以get方式请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static string WebClientGet(string url, string token = null)
        {
            WebClientExtend client = new WebClientExtend();
            client.Timeout = 60 * 3;
            client.Encoding = Encoding.UTF8;
            if (!string.IsNullOrWhiteSpace(token))
            {
                client.Headers.Add("Authorization", token);
            }
            return client.DownloadString(url);
        }

        /// <summary>
        /// 同步方式，POST发送请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="json"></param>
        /// <param name="token"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        public static string WebClientPost(string url, string json = null, string token = null, Dictionary<string, string> headers = null)
        {
            if (!string.IsNullOrWhiteSpace(json))
            {
                //特殊符号处理，需要编码，"+"编码为%2B
                json = json.Replace("+", "%2B");
            }
            WebClientExtend client = new WebClientExtend();
            client.Timeout = 60 * 3;
            client.Headers.Add("Content-Type", "application/json");
            //client.Headers.Add("Content-Type", "application/x-www-form-urlencoded ");
            if (!string.IsNullOrWhiteSpace(token))
            {
                client.Headers.Add("Authorization", token);
            }
            //client.
            client.Encoding = Encoding.UTF8;
            if (headers != null)
            {
                foreach (var item in headers)
                {
                    client.Headers.Add(item.Key, item.Value);
                }
            }
            if (string.IsNullOrWhiteSpace(json))
            {
                return client.UploadString(url, "");
            }
            return client.UploadString(url, "POST", json);
        }

    }
}
